package com.shugl.demo.config.init;

import com.shugl.demo.base.Constant;
import com.shugl.demo.entity.SysVersion;
import com.shugl.demo.mapper.SysVersionMapper;
import com.shugl.demo.utils.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.init.ScriptStatementFailedException;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author shugl
 */
@Slf4j
@Component
public class SysInit implements CommandLineRunner {
//public class SysInit {


    @Resource
    private SysVersionMapper sysVersionMapper;
    @Resource
    private DataSource dataSource;

    private String sqlCatalog = (SysUtil.CLASS_PATH + "WEB-INF/sql").replaceAll("/", "\\\\");


    @Override
    public void run(String... args) {
        //执行sql脚本
        this.updateBySqlFile();
    }

    private void updateBySqlFile() {
        List<SysVersion> list = new ArrayList<>();
        //获取sql文件
        Connection conn = null;
        try {
            list = sysVersionMapper.select(null);
        } catch (BadSqlGrammarException e) {
            //基础表不存在 需要初始化 忽略异常
        }
        // 获取WEB-INF/sql下文件
        File file = new File(sqlCatalog);
        List<String> fileNames = new ArrayList<>();
        for (File sql : file.listFiles()) {
            fileNames.add(sql.getName());
        }

        StringBuilder errSqlName = new StringBuilder();
        try {
            conn = dataSource.getConnection();
            if (list.isEmpty()) {
                log.info("项目初始化...");
                this.doSqlByNames(fileNames, errSqlName, conn, null);
                return;
            }

            // 查询时间倒叙最后一条
            SysVersion lastVersion = list.get(list.size() - 1);
            int startIndex = fileNames.indexOf(lastVersion.getSqlName());
            if (startIndex < 0 && Constant.FAIL.equals(lastVersion.getSuccess())) {
                log.error("sql文件：" + lastVersion.getSqlName() + "不存在");
                return;
            }
            Long badVersionId = null;
            if (Constant.SUCCESS.equals(lastVersion.getSuccess())) {
                fileNames = fileNames.subList(startIndex + 1, fileNames.size());
            } else {
                fileNames = fileNames.subList(startIndex, fileNames.size());
                badVersionId = lastVersion.getId();
            }

            if (fileNames.isEmpty()) {
                return;
            }

            log.info("项目升级...");
            //执行获取到的sql文件
            this.doSqlByNames(fileNames, errSqlName, conn, badVersionId);
        } catch (SQLException e1) {
            e1.printStackTrace();
        } catch (ScriptStatementFailedException e2) {

        } finally {
            DataSourceUtils.releaseConnection(conn, dataSource);
        }
    }


    /**
     * 执行sql文件
     *
     * @param fileNames  文件名数组
     * @param errSqlName 执行失败的sql
     * @param conn
     */
    private void doSqlByNames(List<String> fileNames, StringBuilder errSqlName, Connection conn, Long badVersionId) {
        for (String sqlName : fileNames) {
            SysVersion version = new SysVersion();
            version.setSqlName(sqlName);
            errSqlName.replace(0, errSqlName.length(), sqlName);

            log.info("开始执行sql：" + sqlName);
            String path = sqlCatalog + "\\" + sqlName;
            PathResource rc = new PathResource(path);
            EncodedResource er = new EncodedResource(rc, "utf-8");
            Date beginTime = new Date();
            try {
                ScriptUtils.executeSqlScript(conn, er);
            } catch (Exception e) {
                e.printStackTrace();
                //sql执行异常
                if (badVersionId != null) {
                    return;
                }
                version.setCreateTime(new Date());
                sysVersionMapper.insertSelective(version);
                return;
            }
            Date endTime = new Date();

            version.setSuccess(Constant.SUCCESS);
            version.setUseDate(endTime.getTime() - beginTime.getTime());
            if (badVersionId != null) {
                version.setId(badVersionId);
                sysVersionMapper.updateByPrimaryKeySelective(version);
            } else {
                version.setCreateTime(beginTime);
                sysVersionMapper.insertSelective(version);
            }
            badVersionId = null;
            log.info("执行结束，使用时间：" + version.getUseDate() + "ms");
        }


    }


}
